home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / arcers / tar316.zip / SAVEFILE.C < prev    next >
Text File  |  1994-07-21  |  11KB  |  400 lines

  1. /* savefile.c - storying regular files into (tape) archive
  2.  * This is the part of the Tar program (see file tar.c)
  3.  * Author: T.V.Shaporev
  4.  * Creation date 11 Mar 1993
  5.  */
  6. #include <stdio.h>
  7.  
  8. #include "sysup.h"
  9. #include "modern.h"
  10. #include "compress.h"
  11. #include "zippipe.h"
  12. #include "crc32.h"
  13. #include "define.h"
  14.  
  15. extern char longname[];
  16.  
  17. extern char *deleft __ARGS__(( char * ));
  18. extern void newhead __ARGS__(( char *, long ));
  19. extern void prcsum  __ARGS__(( register header * ));
  20. extern void proctl  __ARGS__(( char *, long ));
  21. static void prhexl  __ARGS__(( char *, long ));
  22.  
  23. static void prhexl(dest, l)
  24. char *dest; long l;
  25. {
  26.    register int i;
  27.    static char h[] = "0123456789AbCdEf";
  28.  
  29.    *dest++ = '0'; *dest++ = 'x';
  30.    for (i=32; i;) *dest++ = h[(int)(l >> (i -= 4)) & 15];
  31.    *dest++ = ' '; *dest++ = '\0';
  32. }
  33.  
  34. #ifdef UNIX
  35.     static werelost = FALSE;
  36. #endif
  37.  
  38. #ifdef MSDOS
  39. #    include <string.h>
  40. #    ifdef __TURBOC__
  41. #        include <dir.h>
  42. #    else
  43. #        include <direct.h>
  44. #    endif
  45. #    include <io.h>
  46.  
  47. static int skipdots __ARGS__(( char *, int ));
  48. static int unperiod __ARGS__(( char *, int ));
  49. static int nextchar __ARGS__(( char *, int ));
  50.  
  51. static int skipdots(char *s, int n)
  52. {
  53.    while (n>0 && s[n]=='/' && s[n-1]=='.' && (n<2 || s[n-2]=='/'))
  54.       n -= 2;
  55.    return n;
  56. }
  57.  
  58. static int unperiod(char *s, int n)
  59. {
  60.    while (n>2 && s[n]=='/' && s[n-1]=='.' && s[n-2]=='.' && s[n-3]=='/') {
  61.       if ((n -= 3) > 0) {
  62.          for (n=nextchar(s, n); n>=0 && s[n]!='/'; n--) ;
  63.       }
  64.    }
  65.    return n;
  66. }
  67.  
  68. static int nextchar(char *s, int n)
  69. {
  70.    if (n >= 0) n -= 1;
  71.  
  72.    while (n>0 && s[n]=='/' && s[n-1]=='.' &&
  73.         ((n<2 || s[n-2]=='/') ||
  74.           n>2 && s[n-2]=='.' && s[n-3]=='/')) {
  75.        if (n>1 && s[n-2]=='.') {
  76.           n = unperiod(s, n);
  77.        } else {
  78.           n = skipdots(s, n);
  79.        }
  80.    }
  81.    return n;
  82. }
  83. #else
  84.     int  strlen();
  85.     char *strcpy(), *strcat(), *strncpy();
  86.     int  open(), read(), close(), unlink();
  87.     long lseek();
  88. #endif
  89. #include "lzpack.h"
  90. #include "roll.h"
  91.  
  92. void cantopen(name)
  93. char *name;
  94. {
  95.    (void)fprintf(myout, "Tar: can\'t open \'%s\'\n", name);
  96. }
  97.  
  98. static void tmpput  __ARGS__(( int ));
  99. static void no_mem  __ARGS__(( int ));
  100. static void errproc __ARGS__(( char * ));
  101.  
  102. static void tmpput(c)
  103. int c;
  104. {
  105.    ++codesize; if (rputc(c) != 0) errproc(hblock->m.name);
  106. }
  107.  
  108. static void no_mem(flag)
  109. int flag;
  110. {
  111.    (void)fprintf(stderr, "No memory for encoding.");
  112.    if (flag) {
  113.       (void)fprintf(stderr, " Continue? ");
  114.       if (YES_NO()) return;
  115.    } else {
  116.       (void)fprintf(stderr, "\n");
  117.    }
  118.    done(ESMALL);
  119. }
  120.  
  121. static void errproc(fname)
  122. char *fname;
  123. {
  124.    (void)fprintf(myout, "\nTar: error processing \'%s\'\n", fname);
  125.    done(EINTER);
  126. }
  127.  
  128. void savefile(fname)
  129. char *fname;
  130. {
  131.    register i; register c;
  132.    register char *p;
  133.    register long blocks;
  134.    register packok;
  135.    register struct node *t; struct node *prev;
  136.    int infile; long this;
  137.  
  138.    p = deleft(fname);
  139.    if (u_flag) {
  140.       if ((t = finditem(p, &prev, timehead)) != NONE) {
  141.          i = t->info.time >= st.st_mtime;
  142.          delitem(t, &timehead);
  143.          if (i) return;
  144.       }
  145.    }
  146.    if (isfile) {/* compare file to store with the archive one */
  147. #ifdef UNIX
  148.       if (st.st_ino == sa.st_ino && st.st_dev == sa.st_dev) return;
  149. #endif
  150. #ifdef MSDOS
  151.       /* The following comparison algorithm may fail */
  152.       /* on combination of substed and real drives   */
  153.       register char *p1, *p2;
  154.       register j1, j2;
  155.       register d2;
  156.       char b[2*MAXPATH];
  157.  
  158.       if (st.st_dev != sa.st_dev) goto next;
  159.  
  160.       /* Sinse 'st_dev' field gives the real drive number */
  161.       /* there is no need to compare drive names          */
  162.  
  163.       j1 = strlen(p1 = archname);
  164.       p2 = fname;
  165.       if (p2[0]>='a' && p2[0]<='z' && p2[1]==':') {
  166.          d2 = p2[0] - ('a'-1);
  167.          p2 += 2;
  168.       } else {
  169.          d2 = 0;
  170.       }
  171.       j2 = strlen(p2);
  172.  
  173.       while (j1>0 && p1[j1-1]!='/' && j2>0 && p2[j2-1]!='/') {
  174.          if (p1[--j1] != p2[--j2]) goto next;
  175.       }
  176.       if (p2[0] != '/') {
  177.          *(int *)b = '/';
  178.          (void)getcurdir(d2, b+1);
  179.          takename(b, b);
  180.          i = strlen(b);
  181.          b[i++] = '/';
  182.          strcpy(b+i, p2);
  183.          p2 = b;
  184.          j2 += i;
  185.       }
  186.       do {
  187.          j1 = nextchar(p1, j1);
  188.          j2 = nextchar(p2, j2);
  189.          if (j1 >= 0 && j2 >= 0 && p1[j1] != p2[j2]) goto next;
  190.       } while (j1>=0 && j2>=0);
  191.       if (j1 == j2) return;
  192. #endif
  193.    }
  194. #ifdef MSDOS
  195. next: i = st.st_mode & 0700; st.st_mode |= (i>>3)|(i>>6);
  196. #endif
  197.    if (w_flag && !okwork('a', ' ', &st, fname)) return;
  198.  
  199.    if ((infile = open(fname, O_RDONLY+O_BINARY)) < 0) {
  200.       cantopen(fname); return;
  201.    }
  202.    newhead(fname, st.st_size);
  203. #ifdef UNIX
  204.    if (st.st_nlink > 1) {
  205.       prev = t = linkhead; i = 1;
  206.       while (t && i>0) {
  207.          i = st.st_ino - t->info.data.inode;
  208.          if (!i) i = st.st_dev - t->info.data.device;
  209.          if (i>0) { prev = t; t = t->next; }
  210.       }
  211.       if (i || !t) {/* entry not found */
  212.          if ((t = additem(p, prev, &linkhead)) == NONE) {
  213.             if (!werelost) {
  214.                (void)fprintf(myout,
  215.                              "Tar: out of memory; link(s) lost\n");
  216.                werelost = TRUE;
  217.             }
  218.          } else {
  219.             t->info.data.count  = st.st_nlink - 1;
  220.             t->info.data.device = st.st_dev;
  221.             t->info.data.inode  = st.st_ino;
  222.          }
  223.       } else {/* previous entry found */
  224.          (void)strncpy(hblock->m.linkname, t->name, MAXTNAME);
  225.          hblock->m.filetype = TF_LNK;
  226.          prcsum(hblock);
  227.          if (v_flag) {
  228.             (void)fprintf(myout, "a %s link to %s\n", p, t->name);
  229.          }
  230.          if (--(t->info.data.count) < 1) delitem(t, &linkhead);
  231.          (void)close(infile);
  232.          return;
  233.       }
  234.    }
  235. #endif
  236.    blocks = (st.st_size + (BLKSIZE-1)) / BLKSIZE;
  237.    packok = FALSE;
  238.    if (blocks > 1) {
  239.       if (pktype == PKDEF) {
  240.          if (zipalloc()!=0 || newroll("TAROLLXXXXXX")!=0) {
  241.             delroll();
  242. #ifndef MSDOS
  243.             if (!w_flag) {
  244.                no_mem(0);
  245.             } else
  246. #endif
  247.             {
  248.                no_mem(1);
  249.                pktype = PKNONE;
  250.                goto run;
  251.             }
  252.          }
  253.          (void)rewroll(0);
  254.          if (v_flag) (void)fprintf(stderr, "e %s", p);
  255.          (void)fflush(stderr);
  256.  
  257.          if (zipcreat(tmpput, ZIP_RAW, pklevel) != 0) {
  258.             (void)fprintf(stderr, "Zip error: %s\n", ziperrlist[ziperror]);
  259.             done(EINTER);
  260.          }
  261.          this = 0;
  262.          do {
  263.             if ((i = read(infile, pk_inp, pksize)) < 0) {
  264.                errproc(hblock->m.name);
  265.             }
  266.             if (i > 0) {
  267.                (void)zipwrite(pk_inp, i);
  268.                if (v_flag) percent((this += i), st.st_size);
  269.             }
  270.          } while (i == pksize);
  271.          codesize = zipclose();
  272.       }
  273. #ifdef USE_COMPRESS
  274.       else if (pktype == PKfLZW) {
  275.          if (strlen(hblock->m.name) > MAXTNAME-2) {
  276. #ifndef MSDOS
  277.             if (!w_flag) {
  278.                (void)fprintf(stderr, longname, hblock->m.name, "\n");
  279.             } else
  280. #endif
  281.             {
  282.                (void)fprintf(stderr, longname, hblock->m.name,
  283.                                      " Store uncompressed? ");
  284.                if (YES_NO()) goto run;
  285.             }
  286.             return;
  287.          }
  288.          if (newroll("TAROLLXXXXXX")!=0) {
  289.             delroll();
  290. #ifndef MSDOS
  291.             if (!w_flag) {
  292.                no_mem(0);
  293.             } else
  294. #endif
  295.             {
  296.                no_mem(1);
  297.                pktype = PKNONE;
  298.                goto run;
  299.             }
  300.          }
  301.          if ((i = z_gettab(pklevel)) < pklevel) {
  302.             if (pklevel > 0) {
  303. #ifndef MSDOS
  304.                if (!w_flag) {
  305.                   (void)fprintf(stderr, "Can only handle %d bits.\n", i);
  306.                } else
  307. #endif
  308.                {
  309.                   (void)fprintf(stderr,
  310.                            "Can only handle %d bits. Continue? ", i);
  311.                   pklevel = YES_NO() ? i : -1;
  312.                }
  313.             }
  314.             if (pklevel <= 0) {
  315.                no_mem(1);
  316.                z_reltab();
  317.                pktype = PKNONE;
  318.                goto run;
  319.             }
  320.          }
  321.          (void)rewroll(0);
  322.          if (v_flag) (void)fprintf(stderr, "z %s", p);
  323.          (void)fflush(stderr);
  324.  
  325.          if (cbegin(pklevel, tmpput, st.st_size) < pklevel) no_mem(0);
  326.          this = 0;
  327.          do {
  328.             if ((i = read(infile, pk_inp, pksize)) < 0) {
  329.                errproc(hblock->m.name);
  330.             }
  331.             if (i > 0) {
  332.                cpiece(pk_inp, i);
  333.                if (v_flag) percent((this += i), st.st_size);
  334.             }
  335.          } while (i == pksize);
  336.          codesize = cflush();
  337.       }
  338. #endif
  339.       if (v_flag) (void)fprintf(stderr, "\r");
  340.       if (pkfile) {
  341.          register long b;
  342.  
  343.          if ((b = (codesize + (BLKSIZE-1)) / BLKSIZE) < blocks) {
  344.             packok = TRUE;
  345.             blocks = b;
  346.          } else if (lseek(infile, 0L, 0) < 0) {
  347.             (void)fprintf(myout, "Tar: \'%s\' seek error\n", fname);
  348.             done(ERREAD);
  349.          }
  350.       }
  351.    }
  352. run : if (v_flag || j_flag) {
  353.       (void)fprintf(myout, "a %s %ld blocks\n", p, blocks);
  354.    }
  355.    if (j_flag) {
  356.       (void)fprintf(stderr, "> ");
  357.       for (i=0; (c=getc(myinp))!='\n'; ) {
  358.          if (i < sizeof(hblock->m.comment)-1) {
  359.             hblock->m.comment[i++] = c;
  360.          }
  361.       }
  362.       hblock->m.comment[i] = 0;
  363.    } else {
  364.       hblock->m.comment[0] = 0;
  365.    }
  366.    if (packok) {
  367.       proctl(hblock->m.size, codesize);
  368.       if (pktype == PKfLZW) {
  369.          (void)strcat(hblock->m.name, ".Z");
  370.       } else { /* pktype == PKDEF */
  371.          prhexl(hblock->m.srcsum, getcrc());
  372.          prhexl(hblock->m.srclen, st.st_size);
  373.       }
  374.       prcsum(hblock);
  375.  
  376.       if (rewroll(1) != 0) errproc(p);
  377.       while (codesize-- > 0) {
  378.          if ((c = rgetc()) == EOF) errproc(p);
  379.          writebyte(c);
  380.       }
  381.    } else {/* common store file */
  382.       prcsum(hblock);
  383.  
  384.       if ((blocks -= writearch(infile, st.st_size, fname)) != 0) {
  385.          (void)fprintf(myout, "Tar: \'%s\' decreased size\n", fname);
  386.          while (blocks-- > 0) nullblock(steptape());
  387.       }
  388.    }
  389.    (void)close(infile);
  390.  
  391.    if (y_flag) {
  392. #ifdef MDSOS
  393.       if (!(st.st_mode & S_IWRITE)) (void)chmod(fname, S_IWRITE);
  394. #endif
  395.       if (unlink(fname)) {
  396.          (void)fprintf(myout, "Tar: can\'t delete \'%s\'\n", fname);
  397.       }
  398.    }
  399. }
  400.